iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0

昨天看完簡單到有點出奇的useRef,今天來看基礎的useContext吧!

React的context可以讓我們避免prop drilling的問題,不用一直將prop傳到子層的子層的子層的子層...(略),而是在需要使用的元件,使用useContext取得要用的值即可。

為了示範方便,讓我們一樣用App.tsx檔案來做範例吧,但正常開發時,通常會選擇將context另外放一個資料夾,比較方便管理。(React資料夾結構設計,各有擁護者,這邊就不贅述了。)

在App.tsx裏,寫下這些未完成的code:

import { useContext, createContext, useState } from "react"

const defaultInfoValue = { name: "John", age: 18 }
const InfoContext = createContext<typeof defaultInfoValue>(defaultInfoValue)

const App = () => {

  return (
    <InfoContext. //不打完
  )
}

export default App

在上面,我們做了:

宣告了一個預設值defaultInfoValue,並將他傳入createContext當做InfoContext的起始值。
這邊我們刻意明確的將InfoContext的型別宣告為<typeof defaultInfoValue>,因為我已經有了一個類似形狀的物件defaultValue,所以我透過關鍵字typeof(可以回去看看第20天的文章),取得特定變數defaultValue的型別形狀。
你在這邊沒有強制宣告型別是沒有關係的,但要是能明確一點也不是什麼壞事。

在未完成的App元件的return statement當中,有一個沒打完的<InfoContext.,打到這邊,你會發現,編輯器又提示了我們,有哪些東西是能從InfoContext中取用的了!有ConsumerProviderdisplayName,這邊我們只需要使用Provider即可,因為我們要設定一個值,讓子層的任何元件都能取用得到。(displayName我還是看了型別宣告檔才知道他要幹嘛,簡單來說,在你設定名稱後,你能在react devTool中清楚看到這個context的名稱。)

VSCode推薦你的屬性/方法

讓我們繼續吧:

//略過import

//你後來會發現,我們這行設定的預設值都不會用到,但我們還是能用這些值來設定型別
const defaultInfoValue = { name: "John", age: 18 }
const InfoContext = createContext<typeof defaultInfoValue>(defaultInfoValue)

const AnotherComponent = () => {
  //這邊不主動宣告型別也是可以,但我還是想寫清楚
  const info = useContext<typeof defaultInfoValue>(InfoContext)
  

  return (
    <>
      <div>{info.name}</div> 
      <div>{info.}</div> //沒打完
    </>
  )
}

const App = () => {
  const [info, setInfo] = useState<typeof defaultInfoValue>({
    name: "Allen",
    age: 200
  })

  return (
    <InfoContext.Provider value={info}>
      <AnotherComponent />
    </InfoContext.Provider>
  )
}

再接續剛剛的話題,我們透過Provider,便能將特定的值給傳到子層去。傳遞方法就是將值傳到value這個key中。這邊我們使用了用useState初始化的值,並且主動的宣告了他的型別為:"跟defaultInfoValue一樣的型別",然後“再次”給他了"初始值"(??)。
所以你會注意到,最早的defaultInfoValue已經被覆蓋過去不太重要了,他現在唯一的功能就是提供初始的物件型別形狀而已。

在App上方,我另外宣告了一個元件AnotherComponent,並在內部使用useContext,需要傳入的值,當然是我們早前用createContext創立的context(好饒口),所以會變成useContext(InfoContext),如此一來,我們就得到了內含nameageinfo物件!

在return statement當中,取用info物件時,你又能發現,編輯器又幫我們推薦能使用的方法/屬性了!

所以,TypeScript與useContext之間的關係,就是這麼簡單。你一定會說:現實中的專案哪有怎麼單純的context。但擁有了我們先前講到的「透過hover去看編輯器預期的型別」,以及閱讀型別宣告檔的經驗,你應該能主動擴充任何的context而不報錯。

在這篇文章,我們順利看了useContext怎麼跟TypeScript結合,還順便複習了typeof關鍵字於TypeScript內的用法,且再次發現編輯器有多麽好用。

那我們明天繼續看別的hook吧!


上一篇
第24天!TypeScript 與 useRef!
下一篇
第26天!TypeScript與useReducer!
系列文
你也對開始使用typescript感到無力嗎?我也是 - 30天初探typescript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言